"use strict";
cc._RF.push(module, '78b52dtdzVK8YwLsUexv0Is', 'GameWorld');
// cases/entity/GameWorld.ts

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var GridCell_1 = require("./GridCell");
var Path_1 = require("./Path");
// import Wall from "./Wall";
var tempvec2 = cc.v2();
Math.sign = Math.sign || function (number) { return number > 0 ? 1 : number < 0 ? -1 : 0; };
var GameWorld = /** @class */ (function () {
    function GameWorld(originX, originY, width, height) {
        // private _walls: Wall[] = [];
        // public get walls(): Wall[] {
        //     return this._walls;
        // }
        // public set walls(value: Wall[]) {
        //     this._walls = value;
        // }
        this._obstacles = [];
        this._agents = [];
        this.path = null;
        this.rect = null;
        this.cellHalfWidth = GameWorld.cellWidth * 0.5;
        this.cellHalfHeight = GameWorld.cellHeight * 0.5;
        this.cols = 0; //
        this.rows = 0;
        this.isDebug = true;
        //flow field
        this.gridCells = [];
        //计算视野
        //如果您是目标单元格，则您有直接线 - 如果您是目标单元格的直接直线邻居，那你也有直接直线
        this.losGrid = [];
        this._openList = []; //开放列表
        this.path = new Path_1.default();
        this.rect = new cc.Rect(originX, originY, width, height);
        this.rows = height / GameWorld.cellHeight;
        this.cols = width / GameWorld.cellWidth;
        this.gridCells = [];
        for (var col = 0; col < this.cols; col++) {
            this.gridCells.push([]);
            this.losGrid.push([]);
            for (var row = 0; row < this.rows; row++) {
                this.gridCells[col].push(new GridCell_1.default(col, row));
                this.losGrid[col].push(false);
            }
        }
        for (var obnum = 0; obnum < 7; obnum++) {
            var row = Math.floor(Math.random() * this.rows);
            var col = Math.floor(Math.random() * this.cols);
            this.gridCells[col][row].cost = Number.MAX_SAFE_INTEGER;
        }
    }
    GameWorld.prototype.tagVehiclesWithinViewRange = function (_vehicle, _viewDistance) {
        for (var i = 0, len = this._agents.length; i < len; i++) {
            var agent = this._agents[i];
            if (agent.ID != _vehicle.ID) {
                agent.isTag = false;
                cc.Vec2.subtract(tempvec2, agent.position, _vehicle.position);
                var range = _viewDistance + agent.radius;
                if (tempvec2.magSqr() < range * range) {
                    agent.isTag = true;
                }
            }
        }
    };
    Object.defineProperty(GameWorld.prototype, "obstacles", {
        get: function () {
            return this._obstacles;
        },
        set: function (value) {
            this._obstacles = value;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(GameWorld.prototype, "agents", {
        get: function () {
            return this._agents;
        },
        set: function (value) {
            this._agents = value;
        },
        enumerable: false,
        configurable: true
    });
    /**
     *生成流场
     *
     * @memberof GameWorld
     */
    GameWorld.prototype.generateFlowField = function (targetCol, targetRow) {
        //计算dijkstra距离
        //重置格子状态
        for (var col = 0; col < this.cols; col++) {
            for (var row = 0; row < this.rows; row++) {
                var gridCell = this.gridCells[col][row];
                this.losGrid[col][row] = false;
                if (!gridCell.cost || gridCell.cost != Number.MAX_SAFE_INTEGER)
                    gridCell.cost = null;
                gridCell.flowDir.set(cc.Vec2.ZERO);
            }
        }
        var pathEnd = this.gridCells[targetCol][targetRow];
        pathEnd.cost = 0;
        this.losGrid[targetCol][targetRow] = true;
        this._openList.length = 0;
        this._openList.push(pathEnd);
        for (var i = 0; i < this._openList.length; i++) {
            var at = this._openList[i];
            if (!(at.row === pathEnd.row && at.col === pathEnd.col)) {
                this.calculateLos(at, pathEnd);
            }
            var neighbors = this.getStraightNeighboursOf(at);
            for (var j = 0, len = neighbors.length; j < len; j++) {
                var neighbor = neighbors[j];
                if (neighbor.cost === null) {
                    neighbor.cost = at.cost + 1;
                    this._openList.push(neighbor);
                }
            }
        }
        //生成流场
        for (var col = 0; col < this.cols; col++) {
            for (var row = 0; row < this.rows; row++) {
                var gridCell = this.gridCells[col][row];
                if (gridCell.cost == Number.MAX_SAFE_INTEGER) {
                    continue;
                }
                if (this.losGrid[col][row]) {
                    cc.Vec2.set(gridCell.flowDir, pathEnd.col - gridCell.col, pathEnd.row - gridCell.row);
                    gridCell.flowDir.normalizeSelf();
                    continue;
                }
                var neighbours = this.getAllNeighboursOf(gridCell);
                var min = null;
                var minDist = 0;
                for (var i = 0; i < neighbours.length; i++) {
                    var n = neighbours[i];
                    var dist = n.cost - this.gridCells[col][row].cost;
                    if (dist < minDist) {
                        min = n;
                        minDist = dist;
                    }
                }
                //If we found a valid neighbour, point in its direction
                if (min != null) {
                    cc.Vec2.set(gridCell.flowDir, min.col - gridCell.col, min.row - gridCell.row);
                    gridCell.flowDir.normalizeSelf();
                }
            }
        }
    };
    GameWorld.prototype.calculateLos = function (at, pathEnd) {
        var xDif = pathEnd.col - at.col;
        var yDif = pathEnd.row - at.row;
        var xDifAbs = Math.abs(xDif);
        var yDifAbs = Math.abs(yDif);
        var hasLos = false;
        var xDifOne = Math.sign(xDif);
        var yDifOne = Math.sign(yDif);
        //Check the direction we are furtherest from the destination on (or both if equal)
        // If it has LOS then we might
        //Check in the x direction
        if (xDifAbs >= yDifAbs) {
            if (this.losGrid[at.col + xDifOne][at.row]) {
                hasLos = true;
            }
        }
        //Check in the y direction
        if (yDifAbs >= xDifAbs) {
            if (this.losGrid[at.col][at.row + yDifOne]) {
                hasLos = true;
            }
        }
        //If we are not a straight line vertically/horizontally to the exit
        if (yDifAbs > 0 && xDifAbs > 0) {
            //If the diagonal doesn't have LOS, we don't
            if (!this.losGrid[at.col + xDifOne][at.row + yDifOne]) {
                hasLos = false;
            }
            else if (yDifAbs === xDifAbs) {
                //If we are an exact diagonal and either straight direction is a wall, we don't have LOS
                if (this.gridCells[at.col + xDifOne][at.row].cost === Number.MAX_SAFE_INTEGER || this.gridCells[at.col][at.row + yDifOne].cost === Number.MAX_SAFE_INTEGER) {
                    hasLos = false;
                }
            }
        }
        //It's a definite now
        this.losGrid[at.col][at.row] = hasLos;
    };
    GameWorld.prototype.getStraightNeighboursOf = function (v) {
        var neighbors = [];
        var x = v.x;
        var y = v.y;
        if (x > 0) {
            neighbors.push(this.gridCells[x - 1][y]);
        }
        if (y > 0) {
            neighbors.push(this.gridCells[x][y - 1]);
        }
        if (x < this.cols - 1) {
            neighbors.push(this.gridCells[x + 1][y]);
        }
        if (y < this.rows - 1) {
            neighbors.push(this.gridCells[x][y + 1]);
        }
        return neighbors;
    };
    GameWorld.prototype.getAllNeighboursOf = function (currentCell) {
        var res = [], x = currentCell.col, y = currentCell.row;
        var up = this.isVaildGrid(x, y - 1), down = this.isVaildGrid(x, y + 1), left = this.isVaildGrid(x - 1, y), right = this.isVaildGrid(x + 1, y);
        //We test each straight direction, then subtest the next one clockwise
        if (left) {
            res.push(this.gridCells[x - 1][y]);
            //left up
            if (up && this.isVaildGrid(x - 1, y - 1)) {
                res.push(this.gridCells[x - 1][y - 1]);
            }
        }
        if (up) {
            res.push(this.gridCells[x][y - 1]);
            //up right
            if (right && this.isVaildGrid(x + 1, y - 1)) {
                res.push(this.gridCells[x + 1][y - 1]);
            }
        }
        if (right) {
            res.push(this.gridCells[x + 1][y]);
            //right down
            if (down && this.isVaildGrid(x + 1, y + 1)) {
                res.push(this.gridCells[x + 1][y + 1]);
            }
        }
        if (down) {
            res.push(this.gridCells[x][y + 1]);
            //down left
            if (left && this.isVaildGrid(x - 1, y + 1)) {
                res.push(this.gridCells[x - 1][y + 1]);
            }
        }
        return res;
    };
    GameWorld.prototype.render = function (pen) {
        pen.node.removeAllChildren();
        for (var col = 0; col < this.cols; col++) {
            for (var row = 0; row < this.rows; row++) {
                var gridCell = this.gridCells[col][row];
                var bottomX = this.rect.xMin + gridCell.col * GameWorld.cellWidth;
                var bottomY = this.rect.yMax - (gridCell.row + 1) * GameWorld.cellHeight;
                pen.rect(bottomX, bottomY, GameWorld.cellWidth, GameWorld.cellHeight);
                if (gridCell.cost === Number.MAX_SAFE_INTEGER) {
                    pen.fillColor = cc.Color.RED;
                    pen.fill();
                }
                else if (this.losGrid[col][row]) {
                    pen.fillColor = cc.Color.GRAY;
                    pen.fill();
                }
                else {
                    pen.stroke();
                }
                if (!gridCell.flowDir.equals(cc.Vec2.ZERO)) {
                    var centerx = bottomX + GameWorld.cellWidth * 0.5;
                    var centery = bottomY + GameWorld.cellHeight * 0.5;
                    var node = new cc.Node();
                    var label = node.addComponent(cc.Label);
                    label.string = "" + gridCell.cost.toFixed(1);
                    label.fontSize = 20;
                    node.setPosition(centerx, centery);
                    node.parent = pen.node;
                    pen.moveTo(centerx, centery);
                    var vec2 = gridCell.flowDir.mul(25);
                    pen.lineTo(centerx + vec2.x, (centery - vec2.y));
                    pen.stroke();
                }
            }
        }
    };
    /**
     *检测格子是否在网格地图内
     *
     * @private
     * @param {number} col
     * @param {number} row
     * @return {*}
     * @memberof GameWorld
     */
    GameWorld.prototype.isVaildGrid = function (col, row) {
        if (row >= 0 && row < this.rows && col >= 0 && col < this.cols) {
            return !this.isBlockedCell(col, row);
        }
        return false;
    };
    /**
     *对应行列是否是障碍
     *
     * @private
     * @param {*} row
     * @param {*} col
     * @return {*}
     * @memberof GameWorld
     */
    GameWorld.prototype.isBlockedCell = function (col, row) {
        var gridCell = this.gridCells[col][row];
        return gridCell.cost === Number.MAX_SAFE_INTEGER;
    };
    /**
     *根据坐标获取行列值
     *
     * @param {number} x
     * @param {number} y
     * @param {number[]} [out]
     * @return {*}
     * @memberof GameWorld
     */
    GameWorld.prototype.getColAndRowByPosition = function (x, y, out) {
        out = out ? out : [];
        out[0] = Math.floor((x - this.rect.xMin) / GameWorld.cellWidth);
        out[1] = Math.floor((this.rect.height - y + this.rect.yMin) / GameWorld.cellHeight);
        return out;
    };
    GameWorld.prototype.getPixelCenterInTilePos = function (col, row) {
        var x = col * GameWorld.cellWidth + this.cellHalfWidth + this.rect.xMin;
        var y = this.rect.height - (row * GameWorld.cellHeight + this.cellHalfHeight) + this.rect.yMin;
        return [x, y];
    };
    GameWorld.cellWidth = 64;
    GameWorld.cellHeight = 64;
    return GameWorld;
}());
exports.default = GameWorld;

cc._RF.pop();